package cn.jane.bigevent.controller;

import cn.jane.bigevent.entity.Result;
import cn.jane.bigevent.entity.User;
import cn.jane.bigevent.service.UserService;
import cn.jane.bigevent.util.JwtUtil;
import cn.jane.bigevent.util.Md5Util;
import cn.jane.bigevent.util.ThreadLocalUtil;
import jakarta.validation.constraints.Pattern;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import org.hibernate.validator.constraints.URL;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

/**
 * 用户模块
 */
@Validated
@RestController
@RequestMapping("/user")
public class UserController {

    private final UserService userService;
    private final StringRedisTemplate stringRedisTemplate;

    public UserController(UserService userService, StringRedisTemplate stringRedisTemplate) {
        this.userService = userService;
        this.stringRedisTemplate = stringRedisTemplate;
    }

    /**
     * 注册
     */
    @PostMapping("/register")
    public Result<Object> register(
            @Pattern(regexp = "^\\S{5,16}$") String username,
            @Pattern(regexp = "^\\S{5,16}$") String password) {
        // 查询用户，如果用户名被占用，则直接返回
        User u = userService.findByUsername(username);
        if (u != null) {
            return Result.error("用户名已被占用");
        }
        userService.register(username, password);
        return Result.success();
    }

    /**
     * 登录
     */
    @PostMapping("/login")
    public Result<Object> login(
            @Pattern(regexp = "^\\S{5,16}$") String username,
            @Pattern(regexp = "^\\S{5,16}$") String password) {
        User loginUser = userService.findByUsername(username);
        if (loginUser == null) {
            return Result.error("用户名错误");
        }
        if (Md5Util.getMD5String(password).equals(loginUser.getPassword())) {
            String token = JwtUtil.generateToken(Map.of("id", loginUser.getId(), "username", loginUser.getUsername()));
            stringRedisTemplate.opsForValue().set(token, "token", 1, TimeUnit.HOURS);
            return Result.success(token);
        } else {
            return Result.error("密码错误");
        }
    }

    /**
     * 获取用户信息
     */
    @GetMapping("/info")
    public Result<User> userInfo() {
        return Result.success(userService.findByUsername(ThreadLocalUtil.getUsername()));
    }

    /**
     * 更新用户信息
     */
    @PutMapping("/update")
    public Result<Object> update(@Validated @RequestBody User user) {
        userService.update(user);
        return Result.success();
    }

    /**
     * 更新用户头像
     */
    @PatchMapping("/avatar")
    public Result<Object> updateAvatar(@URL @RequestParam String avatarUrl) {
        userService.updateAvatar(avatarUrl);
        return Result.success();
    }

    /**
     * 更新用户密码
     */
    @PatchMapping("/password")
    public Result<Object> updatePassword(
            @RequestBody Map<String, String> params,
            @RequestHeader("Authorization") String token) {
        String oldPassword = params.get("oldPassword");
        String newPassword = params.get("newPassword");
        if (!StringUtils.hasLength(oldPassword) || !StringUtils.hasLength(newPassword)) {
            return Result.error("缺少必要的参数");
        }

        if (!newPassword.matches("^\\S{5,16}$")) {
            return Result.error("新密码应该是5~16位的字符");
        }

        User user = userService.findByUsername(ThreadLocalUtil.getUsername());
        if (!Md5Util.getMD5String(oldPassword).equals(user.getPassword())) {
            return Result.error("原密码错误");
        }

        userService.updatePassword(newPassword);
        stringRedisTemplate.delete(token);
        return Result.success();
    }
}
